package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.models.*;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;

import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIotConfigProperties;
import com.zzyl.service.IotService;

import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.aliyun.iot20180120.Client;

import java.util.ArrayList;
import java.util.List;

@Service
public class IotServiceImpl implements IotService {

    @Autowired
    private Client client;

    @Autowired
    private AliIotConfigProperties aliIoTConfigProperties;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void getDeviceList() {
        QueryProductListRequest request = new QueryProductListRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setPageSize(200);
        request.setCurrentPage(1);
        QueryProductListResponse queryProductListResponse = null;
        try {
            queryProductListResponse = client.queryProductList(request);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (queryProductListResponse.getBody().getSuccess()) {
            List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo = queryProductListResponse.getBody().getData().list.productInfo;
            redisTemplate.opsForValue().set(CacheConstants.PRODUCT_LIST, JSONUtil.toJsonStr(productInfo));
        }
    }

    @Override
    public List<ProductVo> getAllProduct() {
        String s = redisTemplate.opsForValue().get(CacheConstants.PRODUCT_LIST);
        List<ProductVo> productVos = JSONUtil.toList(s, ProductVo.class);
        return productVos;
    }

    @Override
    public void RegisterDevice(DeviceDto deviceDto) {
        //设备名称注册设备,先查询是否重复
        int count = deviceMapper.queryDeviceByDeviceName(deviceDto.getDeviceName());
        if (count > 0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        //注册设备
        RegisterDeviceRequest deviceRequest = new RegisterDeviceRequest();
        deviceRequest.setProductKey(deviceDto.getProductKey());
        deviceRequest.setDeviceName(deviceDto.getDeviceName());
        deviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        deviceRequest.setNickname(deviceDto.getNickname());
        RegisterDeviceResponse registerDeviceResponse = null;
        try {
            registerDeviceResponse = client.registerDevice(deviceRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


        //注册成功
        //保存到数据库
        if (registerDeviceResponse.getBody().getSuccess()) {
            Device device = BeanUtil.toBean(deviceDto, Device.class);
            //注册设备成功后有设备id
            device.setIotId(registerDeviceResponse.getBody().getData().getIotId());
            //获取产品名称，发送请求
            QueryProductRequest queryProductRequest = new QueryProductRequest();
            queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            queryProductRequest.setProductKey(deviceDto.getProductKey());
            try {
                QueryProductResponse queryProductResponse = client.queryProduct(queryProductRequest);
                if (queryProductResponse.getBody().getSuccess()) {
                    device.setProductName(queryProductResponse.getBody().getData().getProductName());
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            //如果是随身设备物理位置就设为null
            if (deviceDto.getLocationType().equals(0)) {
                device.setPhysicalLocationType(-1);
            }

            //保存到数据库，如果保存报错就删除设备
            try {
                device.setHaveEntranceGuard(0);
                deviceMapper.saveDevice(device);
            } catch (Exception e) {
                //删除设备
                DeleteDeviceRequest request = new DeleteDeviceRequest();
                request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
                request.setIotId(device.getIotId());
                request.setProductKey(device.getProductKey());
                request.setDeviceName(device.getDeviceName());
                try {
                    DeleteDeviceResponse deleteDeviceResponse = client.deleteDevice(request);
                    if (deleteDeviceResponse.getBody().getSuccess()) {
                        throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
                    }
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }
        } else {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
    }

    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePage) {
        PageHelper.startPage(devicePage.getPageNum(), devicePage.getPageSize());
        Page<DeviceVo> page = deviceMapper.selectByPage(devicePage);
        return PageResponse.of(page, DeviceVo.class);
    }

    @Override
    public DeviceVo queryDeviceDetail(DeviceDto deviceDto) {
        DeviceVo deviceVo = deviceMapper.queryDeviceDetail(deviceDto);

        QueryDeviceDetailRequest request = new QueryDeviceDetailRequest();
        request.setDeviceName(deviceDto.getDeviceName());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());
        request.setIotId(deviceVo.getIotId());
        QueryDeviceDetailResponse response = null;
        try {
            response = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!response.getBody().getSuccess()){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = response.getBody().getData();
        BeanUtil.copyProperties(data, deviceVo, CopyOptions.create().setIgnoreNullValue(true));

        return deviceVo;
    }

    @Override
    public ResponseResult queryDevicePropertyStatus(DeviceDto deviceDto) {
        QueryDevicePropertyStatusRequest request = new QueryDevicePropertyStatusRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());
        Device device = deviceMapper.selectByDeviceName(deviceDto.getDeviceName());
        request.setIotId(device.getIotId());
        QueryDevicePropertyStatusResponse response = null;
        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!response.getBody().getSuccess()) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
        QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData data = response.getBody().getData();

        return ResponseResult.success(data);
    }

    @Override
    public ResponseResult queryThingModelPublished(DeviceDto deviceDto) {
        QueryThingModelPublishedRequest request = new QueryThingModelPublishedRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());
        QueryThingModelPublishedResponse response = null;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!response.getBody().getSuccess()) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData data = response.getBody().getData();

        return ResponseResult.success(data);
    }

    @Override
    public void updateDeviceNikeName(DeviceDto deviceDto) {
        int i = deviceMapper.queryDeviceByDeviceName(deviceDto.getDeviceName());
        if (i == 0) {
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo = BeanUtil.copyProperties(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> list = new ArrayList<>();
        list.add(nicknameInfo);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setDeviceNicknameInfo(list);
        BatchUpdateDeviceNicknameResponse response = null;
        try {
            response = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (response.getBody().getSuccess()) {
            Device device = BeanUtil.toBean(deviceDto, Device.class);
            deviceMapper.updateDeviceNikeName(device);
        } else {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

    }

    @Override
    public void deleteByIotId(DeviceDto deviceDto) {
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setIotId(deviceDto.getIotId());
        request.setProductKey(deviceDto.getProductKey());
        request.setDeviceName(deviceDto.getDeviceName());
        try {
            DeleteDeviceResponse response = client.deleteDevice(request);
            if (response.getBody().getSuccess()) {
                Device device = BeanUtil.toBean(deviceDto, Device.class);
                deviceMapper.deleteByIotId(device);
            } else {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


}
